/*
 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <hi_task.h>
#include <hi_wifi_api.h>
#include <hi_mux.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include "iot_config.h"
#include "iot_log.h"
#include "iot_main.h"
#include "iot_profile.h"
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_i2c.h"
#include "iot_gpio.h"
#include "iot_errno.h"
#include "iot_uart.h"
#include "iot_gpio_ex.h"

#include "oled_ssd1306.h"

#define frame_head (1<<15)
#define data_add (1<<14)
#define data_id (1<<13)
#define data_len (1<<12)
#define TAKE_THE_INITIATIVE_TO_REPORT
#define ONE_SECOND                          (1000)

/* oc request id */
#define CN_COMMADN_INDEX                    "commands/request_id="
#define WECHAT_SUBSCRIBE_LIGHT              "light"
#define WECHAT_SUBSCRIBE_LIGHT_ON_STATE     "1"
#define WECHAT_SUBSCRIBE_LIGHT_OFF_STATE    "0"

uint8_t* data_receive(uint8_t data_buff);
int data_receive_callback(uint8_t* receive_data_buff);
uint8_t* receive_data_buff = NULL;
uint16_t receive_flag;
uint32_t usart_data_len;
uint8_t  receibe_add_buff;
uint8_t  receibe_id_buff;
uint8_t  receibe_len_buff;
uint8_t addcheck;
uint8_t sumcheck;
uint8_t data_finish;

//定义递增变量
int num = 0;

int g_ligthStatus = -1;
typedef void (*FnMsgCallBack)(hi_gpio_value val);
typedef struct FunctionCallback {
    hi_bool  stop;
    hi_u32 conLost;
    hi_u32 queueID;
    hi_u32 iotTaskID;
    FnMsgCallBack    msgCallBack;
}FunctionCallback;
FunctionCallback g_functinoCallback;

//UART配置函数
int intusr_uart2_config(void)
{
    int ret;
//初始化UART2配置，115200，数据bit为8,停止位1，奇偶校验为NONE，流控为NONE
    IotUartAttribute g_uart2_cfg = {115200, 8, 1, IOT_UART_PARITY_NONE, 0,0,0};

    ret = IoTUartInit(1, &g_uart2_cfg);

    if (ret != 0)
    {
        printf("uart1 init fail\r\n");
    }
    return ret;
}

//延时函数
unsigned int TaskMsleep(unsigned int ms)
{
    if (ms <= 0) {
        return HI_ERR_FAILURE;
    }
    return hi_sleep((hi_u32)ms);
}

//控制灯的GPIO
static void DeviceConfigInit(hi_gpio_value val)
{
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
}

//回调函数
static int  DeviceMsgCallback(FnMsgCallBack msgCallBack)
{
    g_functinoCallback.msgCallBack = msgCallBack;
    return 0;
}

//小程序端控制函数 
static void wechatControlDeviceMsg(hi_gpio_value val)
{
    DeviceConfigInit(val);
}

// < this is the callback function, set to the mqtt, and if any messages come, it will be called
// < The payload here is the json string
static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)
{
    IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload);
    /* 云端下发命令后，板端的操作处理 */
    if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT) != NULL) {
        if (strstr(payload, WECHAT_SUBSCRIBE_LIGHT_OFF_STATE) != NULL) {
            wechatControlDeviceMsg(HI_GPIO_VALUE1);
            g_ligthStatus = HI_FALSE;
        } else {
            wechatControlDeviceMsg(HI_GPIO_VALUE0);
            g_ligthStatus = HI_TRUE;
        }
    }
    return HI_NULL;
}

/* publish sample */
hi_void IotPublishSample(int number)
{
    /* reported attribute */
    WeChatProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
        /* report motor */
        .reportAction.subDeviceActionMotor = "motor",
        .reportAction.motorActionStatus = 0, /* 0 : motor off */
        /* report temperature */
        .reportAction.subDeviceActionTemperature = "temperature",
        .reportAction.temperatureData = 30, /* 30 :temperature data */
        /* report humidity */
        .reportAction.subDeviceActionHumidity = "humidity",   //改次数
        .reportAction.humidityActionData = number, /* humidity data */
        /* report light_intensity */
        .reportAction.subDeviceActionLightIntensity = "light_intensity",
        .reportAction.lightIntensityActionData = 60, /* 60 : light_intensity */
    };

    /* report light */
    if (g_ligthStatus == HI_TRUE) {
        weChatProfile.reportAction.subDeviceActionLight = "light";
        weChatProfile.reportAction.lightActionStatus = 1; /* 1: light on */
    } else if (g_ligthStatus == HI_FALSE) {
        weChatProfile.reportAction.subDeviceActionLight = "light";
        weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */
    } else {
        weChatProfile.reportAction.subDeviceActionLight = "light";
        weChatProfile.reportAction.lightActionStatus = 0; /* 0: light off */
    }
    /* profile report */
    IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile);
}

//主任务函数
static void OledmentTask(const char *arg)
{
    (void)arg;
    // unsigned char buf[16];
    uint8_t buf[1];
    unsigned int len = 0;


    (void)arg;
    IoTGpioInit(0);
    IoTGpioInit(1);
    IoSetFunc(0,IOT_IO_FUNC_GPIO_0_UART1_TXD);
    IoSetFunc(1,IOT_IO_FUNC_GPIO_1_UART1_RXD);
    WifiStaReadyWait();
    cJsonInit();
    IoTMain();
    /* 云端下发回调 */
    IoTSetMsgCallback(DemoMsgRcvCallBack);
    /* 主动上报 */
    printf("UART1 init...\r\n");
    intusr_uart2_config();
    #ifdef TAKE_THE_INITIATIVE_TO_REPORT
    while(1)
    {
                IotPublishSample(num); // 发布例程
                g_ligthStatus = HI_FALSE;
#endif
        TaskMsleep(ONE_SECOND);
        // printf("hahahhahahaaa");
        len = IoTUartRead(1,buf, 1);
        if(len)//数据发送给串口2
        {
            if(receive_data_buff == NULL)
            {
                receive_data_buff = data_receive(buf[0]);
            }
            else if(receive_data_buff != NULL)
            {
                if(usart_data_len < receive_data_buff[3]+2)
                {
                    receive_data_buff[4 + usart_data_len++] = buf[0];
                }

                if(usart_data_len >= receive_data_buff[3]+2)
                {
                    for(int i = 0; i < receive_data_buff[3]+4 ; i++)
                    {
                        sumcheck += receive_data_buff[i];
                        addcheck += sumcheck;
                    }
                    if(sumcheck == receive_data_buff[receive_data_buff[3]+4] && addcheck == receive_data_buff[receive_data_buff[3]+5])
                    {
                        int r_data = data_receive_callback(receive_data_buff);
                        if(r_data==1){
                            num++;
                            g_ligthStatus = HI_TRUE;
                        }
                        printf("\n\r");
                        printf("now number:%d",num);
                    }
                    else
                    {
                        for(int i = 0;i < receive_data_buff[3] + 6;i++)
                        printf("0x%X\r\n",receive_data_buff[i]);
                        printf("receive fail...\r\n");
                    }
                    free(receive_data_buff);
                    addcheck = 0;
                    sumcheck = 0;
                    data_finish = 1;
                    receive_data_buff = NULL;
                    usart_data_len = 0;
                }
            }
        }
        free(buf);
    }
   
    
   
}

static void OledDemo(void)
{
    osThreadAttr_t attr;
    attr.name = "OledmentTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4096; /* 任务大小4096 */
    attr.priority = osPriorityNormal;

    if (osThreadNew(OledmentTask, NULL, &attr) == NULL) {
        printf("[OledDemo] Falied to create OledmentTask!\n");
    }
}

//解码函数
uint8_t* data_receive(uint8_t data_buff)
{
    if(data_buff == 0xAA)
    {
        receive_flag |= frame_head;
    }
    else if(receive_flag & frame_head)
    {
        if((receive_flag & frame_head) && ((receive_flag & data_add) == 0))
        {
            receibe_add_buff = data_buff;
            receive_flag |= data_add;
        }
        else if((receive_flag & data_add) && ( (receive_flag & data_id) == 0))
        {
            receive_flag |= data_id;
            receibe_id_buff = data_buff;
        }
        else if((receive_flag & data_add) && (receive_flag & data_id) && ( (receive_flag & data_len) == 0 ))
        {
            receive_flag |= data_len;
            receibe_len_buff = data_buff;
            uint8_t* receive_data_buff = (uint8_t*) malloc(data_buff + 6);
            if(receive_data_buff == NULL)
            {
                printf("receive fail error code 0..\r\n");
                return NULL;
            }
            receive_data_buff[0] = 0xAA;
            receive_data_buff[1] = receibe_add_buff;
            receive_data_buff[2] = receibe_id_buff;
            receive_data_buff[3] = receibe_len_buff;
            receive_flag = 0;
            receibe_add_buff = 0;
            receibe_id_buff = 0;
            receibe_len_buff = 0;
            return receive_data_buff;
        }
        else
        {
            receive_flag = 0;
            receibe_add_buff = 0;
            receibe_id_buff = 0;
            receibe_len_buff = 0;
            printf("receive fail error code 1..\r\n");
            return NULL;
        }
    }
    return NULL;
}

//获取传输信息
int data_receive_callback(uint8_t* receive_data_buff)
{
    int data1,data2,data3;
    int rec_data;
    data1 =(int)receive_data_buff[4];

    printf("receive success data = %d\n",data1);
    return data1;
}


APP_FEATURE_INIT(OledDemo);